package nl.windgazer.arachne.services.captcha;

import java.awt.Color;
import java.awt.Font;
import java.awt.image.ImageFilter;

import nl.windgazer.arachne.util.ArachneSymbolConstants;

import org.apache.tapestry5.ioc.services.SymbolSource;

import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;
import com.octo.captcha.component.image.backgroundgenerator.UniColorBackgroundGenerator;
import com.octo.captcha.component.image.color.SingleColorGenerator;
import com.octo.captcha.component.image.deformation.ImageDeformation;
import com.octo.captcha.component.image.deformation.ImageDeformationByFilters;
import com.octo.captcha.component.image.fontgenerator.FontGenerator;
import com.octo.captcha.component.image.fontgenerator.RandomFontGenerator;
import com.octo.captcha.component.image.textpaster.DecoratedRandomTextPaster;
import com.octo.captcha.component.image.textpaster.TextPaster;
import com.octo.captcha.component.image.textpaster.textdecorator.BaffleTextDecorator;
import com.octo.captcha.component.image.textpaster.textdecorator.TextDecorator;
import com.octo.captcha.component.image.wordtoimage.DeformedComposedWordToImage;
import com.octo.captcha.component.word.wordgenerator.RandomWordGenerator;
import com.octo.captcha.component.word.wordgenerator.WordGenerator;
import com.octo.captcha.engine.image.ListImageCaptchaEngine;

public class ImageCaptchaEngine extends ListImageCaptchaEngine {

	private SymbolSource _symbolSource;

	ImageCaptchaEngine(SymbolSource symbolSource) {
		_symbolSource = symbolSource;
	}

	@Override
	/**
	 * this method should be implemented as folow : <ul> <li>First construct all the factories you want to initialize
	 * the gimpy with</li> <li>then call the this.addFactoriy method for each factory</li> </ul>
	 */
	protected void buildInitialFactories() {

	    //build filters
	    com.jhlabs.image.WaterFilter water = new com.jhlabs.image.WaterFilter();

	    water.setAmplitude(3d);
	    water.setAntialias(true);
	    water.setPhase(20d);
	    water.setWavelength(70d);


	    ImageDeformation backDef = new ImageDeformationByFilters(
	            new ImageFilter[]{});
	    ImageDeformation textDef = new ImageDeformationByFilters(
	            new ImageFilter[]{});
	    ImageDeformation postDef = new ImageDeformationByFilters(
	            new ImageFilter[]{water});

    	//This is the generator that creates the captcha word from the configured characters
    	WordGenerator wg = new RandomWordGenerator(_symbolSource.valueForSymbol(ArachneSymbolConstants.CAPTCHA_CHARS));

    	//wordtoimage components
	    TextPaster randomPaster = new DecoratedRandomTextPaster(new Integer(6), new Integer(
	            7), new SingleColorGenerator(Color.black)
	            , new TextDecorator[]{new BaffleTextDecorator(new Integer(1), Color.white)});

	    //Setting up the configured background color
    	final int width = Integer.parseInt(_symbolSource.valueForSymbol(ArachneSymbolConstants.CAPTCHA_IMG_WIDTH));
    	final int height = Integer.parseInt(_symbolSource.valueForSymbol(ArachneSymbolConstants.CAPTCHA_IMG_HEIGHT));
    	final Color bgColor = getColor(_symbolSource.valueForSymbol(ArachneSymbolConstants.CAPTCHA_BACKGROUND));
    	BackgroundGenerator back = new UniColorBackgroundGenerator(width,height,bgColor);

    	//Splitting and instantiating the Fonts configured for this app.
    	String[] sFonts = _symbolSource.valueForSymbol(ArachneSymbolConstants.CAPTCHA_FONTS).split(",");
    	Font[] fonts = new Font[sFonts.length];
    	for (int i = 0; i < sFonts.length; i++) {
    		fonts[i] = new Font(sFonts[i], 0, 10);
    	}
    	FontGenerator fontGenerator = new RandomFontGenerator(14, 18, fonts);

	    //word2image 1
	    com.octo.captcha.component.image.wordtoimage.WordToImage word2image;
	    word2image = new DeformedComposedWordToImage(fontGenerator, back, randomPaster,
	            backDef,
	            textDef,
	            postDef
	    );


	    this.addFactory(
	            new com.octo.captcha.image.gimpy.GimpyFactory(wg,
	                    word2image));

	}

	private Color getColor(String hex) {
		int r = Integer.parseInt(hex.substring(0,2),16);
		int g = Integer.parseInt(hex.substring(2,4),16);
		int b = Integer.parseInt(hex.substring(4,6),16);
		int a = hex.length() > 6?Integer.parseInt(hex.substring(6),16):255;
		return new Color(r,g,b,a);
	}

}
